import { useState, useEffect } from 'react';
import { votePost } from '../services/api';
import { ArrowUpIcon, ArrowDownIcon } from '@heroicons/react/24/solid';
import { useVotes } from '../hooks/useVotes';

interface VoteProps {
  postId: number;
  initialUpvotes: number;
  initialDownvotes: number;
}

export default function Vote({ postId, initialUpvotes, initialDownvotes }: VoteProps) {
  const [upvotes, setUpvotes] = useState(initialUpvotes || 0);
  const [downvotes, setDownvotes] = useState(initialDownvotes || 0);
  const { votes, refetchVotes } = useVotes();
  const userVote = votes[postId] || null;

  // This effect ensures that if the initial props change (e.g. navigating
  // between pages), the component's upvote/downvote counts are updated.
  useEffect(() => {
    setUpvotes(initialUpvotes || 0);
    setDownvotes(initialDownvotes || 0);
  }, [initialUpvotes, initialDownvotes]);

  const handleVote = async (voteType: number) => {
    const originalUpvotes = upvotes;
    const originalDownvotes = downvotes;

    // Optimistic UI update for vote counts
    if (userVote === voteType) { // Undoing a vote
      voteType === 1 ? setUpvotes((v) => v - 1) : setDownvotes((v) => v - 1);
    } else if (userVote === -voteType) { // Changing a vote
      if (voteType === 1) {
        setUpvotes((v) => v + 1);
        setDownvotes((v) => v - 1);
      } else {
        setUpvotes((v) => v - 1);
        setDownvotes((v) => v + 1);
      }
    } else { // Casting a new vote
      voteType === 1 ? setUpvotes((v) => v + 1) : setDownvotes((v) => v + 1);
    }

    // The refetchVotes() from the hook will handle updating the button color state
    // by triggering a re-render with the new `votes` map.
    try {
      await votePost(String(postId), voteType);
    } catch (error) {
      console.error('Failed to vote', error);
      // On error, revert the optimistic UI changes
      setUpvotes(originalUpvotes);
      setDownvotes(originalDownvotes);
    } finally {
      // Always refetch from the server to ensure UI is in sync with the backend.
      refetchVotes();
    }
  };

  return (
    <div className="flex items-center space-x-2">
      <button
        onClick={() => handleVote(1)}
        className={`flex items-center space-x-1 rounded-md p-2 transition-colors ${
          userVote === 1 ? 'text-green-500 bg-green-100 dark:bg-green-900' : 'text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800'
        }`}
      >
        <ArrowUpIcon className="h-5 w-5" />
        <span>{upvotes}</span>
      </button>
      <button
        onClick={() => handleVote(-1)}
        className={`flex items-center space-x-1 rounded-md p-2 transition-colors ${
          userVote === -1 ? 'text-red-500 bg-red-100 dark:bg-red-900' : 'text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800'
        }`}
      >
        <ArrowDownIcon className="h-5 w-5" />
        <span>{downvotes}</span>
      </button>
    </div>
  );
}
